<?php

class CommonController extends ApiController
{

    const JOURNAL_FLAG = 'journal';

    const RESOURCE_URL = 'http://www.csapchina.com';

    const CSI_URL = 'http://m.chinashippinginfo.net';

    const SISI_URL = 'http://m.sisi-smu.org';

    protected $userId;

    protected $userIp;

    /**
     * [$flag description]
     * @var string
     */
    protected $flag;

    protected $commentOriginFlag = 3;

    /**
     * [dbRepository description]
     * @param  string $connection 数据库连接名
     * @param  string $name       数据库表名
     * @return object
     */
    protected function dbRepository($connection, $name)
    {
        return DB::connection($connection)->table($name);
    }

    /**
     * common logic for journal
     *
     * @return object
     */
    protected function journal()
    {
        return DB::table('qikan')
            ->select('id', 'thumbnail as thumbnail_url', 'name', 'qname as journal_date')
            ->where('display', 1);
    }

    /**
     * 获取用户 ID
     * 用户未登录返回空字符串 ''
     * 登录用户返回用户 ID
     *
     * @return string
     */
    protected function getUid()
    {
        return (!$this->accessToken) ? '' : ($this->getOwnerId());
    }

    /**
     * 根据 Access Token 获取用户 ID
     *
     * @return string
     */
    protected function getOwnerId()
    {
        $this->authorizer->validateAccessToken();

        return $this->authorizer->getResourceOwnerId();
    }

    /**
     * 判断用户是否收藏期刊
     *
     * @param  string $uid       用户id
     * @param  string $journalId 期刊id
     * @return boolean
     */
    protected function checkUserStar($uid, $journalId)
    {
        $this->models['star'] = $this->dbRepository('major', 'star');

        return $this->models['star']
            ->where('user_id', $uid)
            ->where('journal_id', $journalId)
            ->exists();
    }

    /**
     * 判断用户是否点赞
     *
     * @param  string $uid       用户id
     * @param  string $commentId 评论id
     * @return boolean
     */
    protected function checkUserFavour($uid, $commentId)
    {
        $this->models['favour'] = $this->dbRepository('major', 'favour');

        return $this->models['favour']
            ->where('user_id', $uid)
            ->where('journal_comment_id', $commentId)
            ->where('flag', $this->commentOriginFlag)
            ->exists();
    }

    /**
     * [getOwner description]
     * @param  int    $userId
     * @param  string $userIp
     * @return object|array
     */
    protected function getOwner()
    {
        if ($this->userId !== null) {
            // 返回用户信息
            $user = $this->user()->find($this->userId);
            $user->avatar_url = $this->prependAvatarPrefix($user->avatar_url);

            return $user;
        }
        // 返回匿名用户信息
        return $this->anonymousUser();
    }

    protected function prependAvatarPrefix($avatarUrl)
    {
        return Request::root().$avatarUrl;
    }

    /**
     * 用户信息统一返回
     *
     * @return todo
     */
    protected function user()
    {
        return DB::table('user')
            ->select('avatar_url', 'name', 'email', 'address');
    }

    private function anonymousUser()
    {
        $area = MultiplexController::getArea($this->userIp);

        $defaultAvatarUrl = Config::get('imagecache::paths.avatar_url_prefix').'/default.png';
        $avatarUrl = $this->prependAvatarPrefix($defaultAvatarUrl);

        return (object) [
            'avatar_url'   => $avatarUrl,
            'name' => '来自'.$area.'的用户'
        ];
    }

    /**
     * 更新评论被点赞数量
     *
     * @param  string $id 评论id
     * @return void
     */
    protected function updateCommentFavours($id)
    {
        list($this->connection, $this->table) = $this->getConnection();

        $comment = $this->dbRepository($this->connection, $this->table);

        $delta = ($this->operator === '+') ? 1 : -1;

        if ($delta === -1) {
            // check the delta is valid
            // if it is neccssary to decrement
            // if the current favours of comment is zero
            // it is not nessary to decrement
            $delta = $this->isValid($id);
        }
        // 如果更新的变化量为 0
        // 直接退出，不做处理
        if ($delta === 0) {
            return;
        }

        $comment->where('id', $id)
            // increment 也可以来减少
            ->increment('favours', $delta, array('updated_at' => date('Y-m-d H:i:s')));
    }

    protected function getConnection()
    {
        switch ($this->flag) {
            case '1':
                $connection = 'secondary';
                $table = 'article_comment';
                break;
            case '2':
                $connection = 'thirdly';
                $table = 'article_comment';
                break;
            case '3':
                $connection = 'major';
                $table = 'journal_comment';
                break;
        }

        return [$connection, $table];
    }

    protected function isValid($commentId)
    {
        $favours = DB::connection($this->connection)
            ->table($this->table)
            ->where('id', '=', $commentId)
            ->pluck('favours');

        if ($favours > 0) {
            return -1;
        }

        return 0;
    }

    protected function processCommentResponse($data)
    {
        foreach ($data as $value) {
            $this->commentId = $value->id;

            $value->is_favoured = $this->isFavoured($value->favours);

            $this->userId = $value->user_id;
            $this->userIp = $value->user_ip;
            $value->user  = $this->getOwner();

            $value->relies = $this->getReply();

            // unset($value->user_id, $value->user_ip);
        }

        return $data;
    }

    /**
     * 评论是否被点赞
     *
     * @param  int     $quantity 评论被点赞数量
     * @return boolean
     */
    protected function isFavoured($quantity)
    {
        if ($quantity == 0) {
            return false;
        }

        if (!$this->accessToken) {
            return false;
        }

        $uid = $this->getOwnerId();

        $this->commentOriginFlag = 3;

        return $this->checkUserFavour($uid, $this->commentId);
    }

    /**
     * [getReply description]
     * @param  int $id 评论id
     * @return array
     */
    protected function getReply()
    {
        $replies = $this->dbRepository('major', 'reply')
            ->select('id', 'created_at', 'content', 'user_id', 'user_ip')
            ->where('journal_comment_id', $this->commentId)
            ->orderBy('created_at', 'desc')
            ->take(2)
            ->get();

        foreach ($replies as $reply) {
            $this->userId = $reply->user_id;
            $this->userIp = $reply->user_ip;
            $reply->user  = $this->getOwner();

            unset($reply->user_id, $reply->user_ip);
        }

        return $replies;
    }

    /**
     * 增加数据模型分页
     *
     * @param  object $model 需要分页的数据模型
     * @return void
     */
    protected function addPagination($model)
    {
        // 第几页数据，默认第一页
        $page    = Input::get('page', 1);
        // 每页显示数据条目，默认每页20条数据
        $perPage = Input::get('per_page', 20);
        $page    = intval($page);
        $perPage = intval($perPage);

        if ($page <= 0 || !is_int($page)) {
            $page = 1;
        }
        if (!is_int($perPage) || $perPage < 1 || $perPage > 100) {
            $perPage = 20;
        }
        // skip -- offset , take -- limit
        $model->skip(($page - 1) * $perPage)->take($perPage);
    }

    protected function getJournalById($id)
    {
        $key = 'journals/'.$id;
        if (Cache::has($key)) {
            return Cache::get($key);
        }

        $journal = $this->journal()
            ->find($id);
        $journal->thumbnail_url = self::RESOURCE_URL.'/'.$journal->thumbnail_url;

        $minutes = 3*24*60;
        Cache::put($key, $journal, $minutes);

        return $journal;
    }

    /**
     * 提取标签
     *
     * @param  string $str Article Title or Content
     * @return [type]      [description]
     */
    protected function extractTag($str)
    {
        $tagArr = $this->getAllTagName();

        $tag = array();
        foreach ($tagArr as $value) {
            preg_match('#'.$value.'#', $str, $matches);
            if ($matches) {
                $tag[] = $matches[0];
            }
        }

        return implode(',', $tag);
    }

    protected function getAllTagName()
    {
        $key = 'tag_names';
        if (Cache::has($key)) {
            return Cache::get($key);
        }

        $tagArr = DB::connection('secondary')
            ->table('tag')
            ->lists('name');
        $minutes = 24*60;
        Cache::put($key, $tagArr, $minutes);

        return $tagArr;
    }

    protected function getTagFromComment()
    {
        $tagArr = DB::connection('major')
            ->table('journal_comment')
            ->where('journal_id', '=', $this->journalId)
            ->where('tag', '<>', '')
            ->latest('created_at')
            ->take(8)
            ->lists('tag');

        $tagArr = array_flip(array_count_values($tagArr));

        ksort($tagArr);

        return last($tagArr) ?: '';
    }

    /**
     * get CSI comment via tag
     *
     * @param  string $tag 标签
     * @return todo
     */
    protected function getCsiComment($tag)
    {
        $this->placeholder = ['secondary', '1', self::CSI_URL];

        $comments = $this->getPlaceholderComment($tag);

        foreach ($comments as $comment) {
            $comment->article = $this->getCsiArticle($comment->article_id, $comment->image_flag);
        }

        return $comments;
    }

    protected function getSisiComment($tag)
    {
        $this->placeholder = ['thirdly', '2', self::SISI_URL];

        $comments = $this->getPlaceholderComment($tag);

        foreach ($comments as $comment) {
            $comment->article = $this->getSisiArticleById($comment->article_id);
        }

        return $comments;
    }

    protected function getPlaceholderComment($tag)
    {
        list($connection, $webFlag, $urlPrefix) = $this->placeholder;

        $comments = DB::connection($connection)
            ->table('article_comment')
            ->where('tag', '=', $tag)
            ->latest('created_at')
            ->take(1)
            ->get();
        foreach ($comments as $comment) {
            $functoinName = ($webFlag === '1')
                ? 'getCsiUser' : 'getSisiUser';
            $comment->user = $this->{$functoinName}($comment->user_id, $comment->user_ip);
            if (! starts_with($comment->user->avatar_url, 'http')) {
                $comment->user->avatar_url = $urlPrefix.$comment->user->avatar_url;
            }
            $comment->flag = $webFlag;
            $comment->is_favoured = $this->checkIsFavoured($comment->favours, $comment->id, $webFlag);
            $comment->replies = $this->getPlaceholderCommentReply($comment->id);
        }

        return $comments;
    }

    protected function getPlaceholderCommentReply($commentId)
    {
        list($connection, $flag, $urlPrefix) = $this->placeholder;

        $replies = DB::connection($connection)
            ->table('reply')
            ->where('article_comment_id', '=', $commentId)
            ->where('flag', '=', $flag)
            ->latest('created_at')
            ->take(1)
            ->get();
        foreach ($replies as $reply) {
            $functoinName = ($flag === '1')
                ? 'getCsiUser' : 'getSisiUser';
            $reply->user = $this->{$functoinName}($reply->user_id, $reply->user_ip);
            if (! starts_with($reply->user->avatar_url, 'http')) {
                $reply->user->avatar_url = $urlPrefix.$reply->user->avatar_url;
            }
            // release some var
            unset($reply->user_id, $reply->user_ip, $reply->updated_at);
        }

        $currentReply = $this->getCurrentReply($commentId);

        return array_merge($currentReply, $replies);
    }

    protected function getCurrentReply($commentId)
    {
        list(, $flag) = $this->placeholder;

        $replies = DB::connection('major')
            ->table('reply')
            ->where('journal_comment_id', '=', $commentId)
            ->where('flag', '=', $flag)
            ->latest('created_at')
            ->take(1)
            ->get();
        foreach ($replies as $reply) {
            $this->userId = $reply->user_id;
            $this->userIp = $reply->user_ip;
            $reply->user  = $this->getOwner();
        }

        return $replies;
    }

    protected function getCsiArticle($articleId, $imageFlag)
    {
        $article = ($imageFlag === 0)
            ? MultiplexController::getArticleBrief($articleId)
            : MultiplexController::getImageNewsBrief($articleId);

        return [
            'id'   => $article->Id,
            'name' => $article->Source ?: 'CSI',
        ];
    }

    protected function getSisiArticleById($articleId)
    {
        return DB::connection('sqlsrv')
            ->table('articles')
            ->where('article_id', '=', $articleId)
            ->first(['article_id as id ', 'article_writer as name']);
    }

    protected function checkIsFavoured($favours, $commentId, $flag)
    {
        if ($favours == 0) {
            return false;
        }

        if (! $this->accessToken) {
            return false;
        }

        $uid = $this->getOwnerId();

        $this->commentOriginFlag = $flag;

        return $this->checkUserFavour($uid, $commentId);
    }

    protected function getCsiUser($uid, $ip)
    {
        if ($uid === null) {
            return $this->getAnonymousUserByIp($ip);
        }

        $user = MultiplexController::getUser($uid);

        return (object) [
            'name'       => $user->name,
            'avatar_url' => $user->avatar_url,
        ];
    }

    /**
     * [getAnonymousUserByIp description]
     * @param  [type] $ip [description]
     * @return object stdClass
     */
    protected function getAnonymousUserByIp($ip)
    {
        return (object) [
            'avatar_url' => Config::get('imagecache::paths.avatar_url_prefix').'/default.png',
            'name'       => '来自'.MultiplexController::getArea($this->userIp).'的用户',
        ];
    }

    protected function getSisiUser($uid, $ip)
    {
        if ($uid === null) {
            return $this->getAnonymousUserByIp($ip);
        }

        return DB::connection('thirdly')
            ->table('user')
            ->find($uid, ['display_name as name', 'avatar_url']);
    }

}